package com.web.websocket.handler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


@Slf4j
public class MyWebSocketHandler implements WebSocketHandler {

    // 使用ConcurrentHashMap存储会话，确保线程安全
    // 可以根据需要选择不同的存储方式：
    // 1. 按用户ID存储: Map<String, WebSocketSession>
    // 2. 按会话ID存储: Map<String, WebSocketSession>
    // 3. 存储所有会话: Set<WebSocketSession>
    private static final Map<String, WebSocketSession> SESSIONS = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // 1. 获取用户ID (可以从session attributes获取，这些attributes可以在拦截器中设置)
        String userId = getUserId(session);

        // 2. 存储会话
        SESSIONS.put(userId, session);

        log.info("用户[{}]已连接，当前在线用户数: {}", userId, SESSIONS.size());

        // 3. 可选：发送欢迎消息
        sendMessage(session, "欢迎连接到WebSocket服务器！");
    }


    //假设发送消息格式为 对方id:消息内容
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        String userId = getUserId(session);
        String payload = message.getPayload().toString();

        log.info("收到用户[{}]的消息: {}", userId, payload);

        String duifangId = payload.substring(0,payload.indexOf(":"));
        String msg = payload.substring(payload.indexOf(":")+1);

        // 处理接收到的消息
        // 例如，可以解析JSON消息，并根据消息类型执行不同操作

        // 示例：简单的消息回显
        sendMessage(session, "服务器收到消息: " + payload);
        sendMessage(SESSIONS.get(duifangId), msg);

        // 示例：广播消息给所有用户
        // broadcastMessage("用户[" + userId + "]说: " + payload);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        String userId = getUserId(session);
        log.error("与用户[{}]的连接发生错误", userId, exception);

        // 发生错误时，关闭连接
        if (session.isOpen()) {
            session.close();
        }

        // 从会话存储中移除
        SESSIONS.remove(userId);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        String userId = getUserId(session);

        // 从会话存储中移除
        SESSIONS.remove(userId);

        log.info("用户[{}]断开连接，关闭状态: {}，当前在线用户数: {}",
                userId, closeStatus.getReason(), SESSIONS.size());
    }

    @Override
    public boolean supportsPartialMessages() {
        return false; // 通常不需要支持部分消息
    }

    /**
     * 从WebSocketSession中获取用户ID
     */
    private String getUserId(WebSocketSession session) {
        // 方式1：从session attributes中获取（需要在拦截器中设置）
        Object userIdAttr = session.getAttributes().get("userId");
        if (userIdAttr != null) {
            return userIdAttr.toString();
        }

        // 方式2：从URL路径中提取
        String path = session.getUri().getPath();
        if (path.contains("/chat/")) {
            String[] pathSegments = path.split("/");
            return pathSegments[pathSegments.length - 1]; // 假设格式为 /chat/{userId}
        }

        // 如果没有更好的标识，使用session ID
        return session.getId();
    }

    /**
     * 向指定会话发送消息
     */
    public void sendMessage(WebSocketSession session, String message) {
        if (session != null && session.isOpen()) {
            try {
                session.sendMessage(new TextMessage(message));
                log.debug("消息已发送到会话: {}", session.getId());
            } catch (IOException e) {
                log.error("发送消息失败: {}", e.getMessage(), e);
            }
        } else {
            log.warn("无法发送消息：会话已关闭或为null");
        }
    }

    /**
     * 向指定用户发送消息
     */
    public void sendMessageToUser(String userId, String message) {
        WebSocketSession session = SESSIONS.get(userId);
        if (session != null) {
            sendMessage(session, message);
        } else {
            log.warn("用户[{}]不在线，无法发送消息", userId);
        }
    }

    /**
     * 向所有在线用户广播消息
     */
    public void broadcastMessage(String message) {
        log.info("广播消息给所有用户: {}", message);
        SESSIONS.forEach((userId, session) -> {
            sendMessage(session, message);
        });
    }

    /**
     * 获取在线用户数量
     */
    public int getOnlineCount() {
        return SESSIONS.size();
    }

    /**
     * 判断用户是否在线
     */
    public boolean isUserOnline(String userId) {
        WebSocketSession session = SESSIONS.get(userId);
        return session != null && session.isOpen();
    }

    /**
     * 关闭指定用户的WebSocket连接
     */
    public void closeUserConnection(String userId, String reason) {
        WebSocketSession session = SESSIONS.get(userId);
        if (session != null && session.isOpen()) {
            try {
                session.close(new CloseStatus(1000, reason));
                log.info("已关闭用户[{}]的连接: {}", userId, reason);
            } catch (IOException e) {
                log.error("关闭连接失败: {}", e.getMessage(), e);
            }
        }
    }
}
